from protocols import Interface, advise
from peak.binding.components import Component, Obtain, Make
from random import random
from math import ceil

#------------------------------------------------------------
class IBody(Interface):
    '''Body interface. Body can be mechanical, bio, or other'''
    def getFuelLevel():
        "how long can we operate?"
    def getDamageLevel():
        "are we disabled?"
    
class IPhysiology(IBody):
    '''Physiology interface'''
    def getHeartRate():
        '''provide information about the heart rate'''

class Body(Component):
    '''
    >>> b = Body()
    >>> b.getFuelLevel()
    'half full'
    >>> b.getDamageLevel()
    'minimal damage'
    '''      
    advise(instancesProvide=[IBody])
    def getFuelLevel(self):
        return "half full"
    def getDamageLevel(self):
        return "minimal damage"

class Physiology(Component):
    '''
    >>> p = Physiology()
    >>> p.getHeartRate()
    'nice rhythm!'
    >>> p.body.getFuelLevel()
    'half full'
    >>> p.body.getDamageLevel()
    'minimal damage'
    '''
    advise(instancesProvide=[IPhysiology])
    body = Make(Body, offerAs=[IBody])
    def getHeartRate(self):
        return "nice rhythm!"

#------------------------------------------------------------
class IMind(Interface):
    '''Mind interface'''
    def perceive():
        '''provide perception'''
    def think():
        '''provide 'thought' mechanism'''

class Intellect(Component):
    advise(instancesProvide=[IMind])
    def think(self):
        print "hmmm, fire bad, thinking hard..."

class Vision(Component):
    advise(instancesProvide=[IMind])
    def perceive(self):
        if ceil(random()*2)%2: return "see threat!"

class Hearing(Component):
    advise(instancesProvide=[IMind])
    def perceive(self):
        if ceil(random()*3)%3: return "hear threat!"
#------------------------------------------------------------
class IEmotion(Interface):
    '''Emotion interface'''
    def getIntensity():
        '''provide aa means for obtaining emotional intensities'''

class Emotion(Component):
    '''
    >>> e = Emotion()
    >>> e.vision.perceive() in [None, 'see threat!']
    True
    >>> e.hearing.perceive() in [None, 'hear threat!']
    True
    >>> e.physiology.getHeartRate()
    'nice rhythm!'
    >>> type(e.getIntensity()).__name__
    'int'
    '''
    advise(instancesProvide=[IEmotion])
    def __init__(self):
        self.feeling = 0 
    vision = Make(Vision, offerAs=[IMind])
    hearing = Make(Hearing, offerAs=[IMind])
    physiology = Make(Physiology, offerAs=[IPhysiology])
    def getIntensity(self):
        '''
        Silly emotional intensity method
        '''
        if self.hearing.perceive(): 
            self.feeling -= 1
        else:
            self.feeling += 1
        if self.vision.perceive(): 
            self.feeling -= 1
        else:
            self.feeling += 1
        if self.physiology.getHeartRate(): 
            self.feeling += 1
        else:
            self.feeling -= 1
        return self.feeling

#------------------------------------------------------------
class IMovement(Interface):
    '''Movement interface'''
    def north():
        '''go north'''
    def south():
        '''go south'''

class IAction(Interface):
    '''Action interface'''
    def doSomething():
        '''Determine an agent action'''

class Movement(Component):
    advise(instancesProvide=[IMind])
    def north(self):
        print "you are now one step north of where you were"
    def south(self):
        print "you are now one step south of where you were"

class Action(Component):
    '''
    >>> a = Action()
    >>> a.physiology.getHeartRate()
    'nice rhythm!'
    >>> a.physiology.body.getFuelLevel()
    'half full'
    >>> a.physiology.body.getDamageLevel()
    'minimal damage'
    >>> type(a.emotion.getIntensity()).__name__
    'int'
    >>> a.intellect.think()
    hmmm, fire bad, thinking hard...
    >>> a.movement.north()
    you are now one step north of where you were
    >>> a.doSomething()
    'action!'
    '''
    advise(instancesProvide=[IAction])
    emotion = Make(Emotion, offerAs=[IMind, IPhysiology])
    physiology = Make(Physiology, offerAs=[IPhysiology])
    intellect = Make(Intellect, offerAs=[IMind])
    movement = Make(Movement, offerAs=[IMovement])
    def doSomething(self):
        '''
        Here, we can get info about the agent from
        the various components which comprise it, 
        and produce some action.
        '''
        return "action!"

#------------------------------------------------------------

def _test():
    import doctest, components
    return doctest.testmod(components)

if __name__ == '__main__':
    _test()

'''

Agent components:


'''
